﻿/* ****************************************************************************
 *
 * Copyright (c) Francesco Abbruzzese. All rights reserved.
 * francesco@dotnet-programming.com
 * http://www.dotnet-programming.com/
 * 
 * This software is subject to a dual license model 
 * included in the license.txt file of this distribution.
 * 
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ComponentModel;

namespace BindToolkit
{
    public partial class ObservableDictionary<TKey, TValue>:IDictionary<TKey, TValue>, INotifyPropertyChanged
    {
        private IDictionary<TKey, TValue> originalDictionary;
        public ObservableDictionary(IDictionary<TKey, TValue> originalDictionary)
        {
            this.originalDictionary = originalDictionary;
        }
        public static IDictionary<TKey, BindWrapper> RecursiveWrapDictionary(IDictionary<TKey, TValue> originalDictionary, bool wrapDeep = false, bool wrapEnumerables = false)
        {
            IDictionary<TKey, BindWrapper> res = new Dictionary<TKey, BindWrapper>();
            foreach (KeyValuePair<TKey, TValue> couple in originalDictionary)
            {
                if (couple.Key == null || couple.Value == null) continue;
                res.Add(new KeyValuePair<TKey,BindWrapper>(couple.Key, new BindWrapper(couple.Value, true, true)));
                
            }
            return res;
        }

        public void Add(TKey key, TValue value)
        {
            originalDictionary.Add(key, value);
            OnPropertyChanged(key);
        }

        public bool ContainsKey(TKey key)
        {
            return originalDictionary.ContainsKey(key);
        }

        public ICollection<TKey> Keys
        {
            get { return originalDictionary.Keys; }
        }

        public bool Remove(TKey key)
        {
            bool res = originalDictionary.Remove(key);
            OnPropertyChanged(key);
            return res;
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            return originalDictionary.TryGetValue(key, out value);
        }

        public ICollection<TValue> Values
        {
            get { return originalDictionary.Values; }
        }

        public TValue this[TKey key]
        {
            get
            {
               return originalDictionary[key];
            }
            set
            {
                originalDictionary[key]=value;
                OnPropertyChanged(key);
            }
        }

        public void Add(KeyValuePair<TKey, TValue> item)
        {
            originalDictionary.Add(item);
            OnPropertyChanged(item.Key);
        }

        public void Clear()
        {
            ICollection<TKey> allkeys = originalDictionary.Keys;
            originalDictionary.Clear();
            foreach(TKey key in allkeys) 
            {
                OnPropertyChanged(key);
            }
        }

        public bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return originalDictionary.Contains(item);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            originalDictionary.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return originalDictionary.Count; }
        }

        public bool IsReadOnly
        {
            get { return originalDictionary.IsReadOnly; }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            bool res = originalDictionary.Remove(item);
            OnPropertyChanged(item.Key);
            return res;
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return originalDictionary.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return originalDictionary.GetEnumerator();
        }

        protected void OnPropertyChanged(TKey key)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(string.Format("Item[{0}]", key)));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
